package com.lianheng.cms.common.gen;

import com.jfinal.kit.Kv;
import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.generator.DataDictionaryGenerator;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;
import com.jfinal.template.Engine;

import javax.sql.DataSource;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

/**
 * @Classname JFMVCGenerator
 * @Description TODO
 * @Date 2019/10/19 11:10
 * @Created by yufeng
 */
public class JFMVCGenerator extends JFinalConfig {
    public static final JFMVCGenerator me = new JFMVCGenerator();
    //    protected final JfEnjoy jfEngine = new JfEnjoy();
    protected Kv tablemetaMap = null;


    public TableMeta getTableMeta(String tableName) {
        if (tablemetaMap == null) {
            MetaBuilder metaBuilder = new MetaBuilder(this.dataSource);
            metaBuilder.setDialect(new MysqlDialect());
            List<TableMeta> tableMetas = metaBuilder.build();
            new DataGenerator(this.dataSource, null).rebuildColumnMetas(tableMetas);
            if (tableMetas.size() == 0) {
                System.out.println("TableMeta 数量为 0，不生成任何文件");
                return null;
            }
            Kv kv = Kv.create();
            for (TableMeta tableMeta : tableMetas) {
                kv.set(tableMeta.name, tableMeta);
            }
            tablemetaMap = kv;
        }
        return (TableMeta) tablemetaMap.get(tableName);
    }


    private String toClassNameSmall(String className) {
        return new StringBuffer(className.substring(0, 1).toLowerCase()).append(className.substring(1)).toString();
    }

    private String toPackages(String module) {
        return new StringBuffer(packageBase).append(".").append(module).toString();
    }


    /**
     * 生成validator
     *
     * @param className 类名称
     */
//    public JFMVCGenerator validator(String className) {
//        String packages = toPackages(className);
//
//        String classNameSmall = toClassNameSmall(className);
//        String webRootPath = PathKit.getWebRootPath();
//        render("/service.html",
//                Kv.by("package", packages)
//                        .set("className", className)
//                        .set("classNameSmall", classNameSmall)
//                ,
//                new StringBuilder()
//                        .append(System.getProperty("user.dir"))
//                        .append("/")
//                        .append(srcFolder)
//                        .append("/")
//                        .append(packages.replace(".", "/"))
//                        .append("/")
//                        .append(className)
//                        .append("Validator.java")
//        );
//        return this;
//    }

    /**
     * 生成Controller
     *
     * @param className 类名称
     */
    public JFMVCGenerator controller(String className) {
        String packages = toPackages("controller");
        String classNameSmall = toClassNameSmall(className);
        String webRootPath = PathKit.getWebRootPath();
        render("/controller.html",
                Kv.by("package", packages)
                        .set("className", className)
                        .set("classNameSmall", classNameSmall)
                        .set("modelPackageName", modelPackageName + "." + className)
                        .set("dtoPackageName", packageBase + ".dto." + className)
                        .set("servicePackageName", packageBase + ".service." + className)
                        .set("packageBase", packageBase)
                ,
                new StringBuilder()
                        .append(webRootPath)
                        .append("/")
                        .append(srcFolder)
                        .append("/")
                        .append(packages.replace(".", "/"))
                        .append("/")
                        .append(className)
                        .append("Controller.java")
        );
        return this;
    }

    /**
     * 生成Service
     *
     * @param className 类名称
     * @param tableName 表名
     */
    public JFMVCGenerator service(String className, String tableName) {
        String packages = toPackages("service");

        String classNameSmall = toClassNameSmall(className);
        String webRootPath = PathKit.getWebRootPath();
        StringBuilder append = new StringBuilder()
                .append(webRootPath)
                .append("/")
                .append(srcFolder)
                .append("/")
                .append(packages.replace(".", "/"))
                .append("/")
                .append(className)
                .append("Service.java");

        Kv set = Kv.by("package", packages)
                .set("className", className)
                .set("classNameSmall", classNameSmall)
                .set("modelPackageName", modelPackageName + "." + className)
                .set("servicePackageName", packageBase + ".service." + className)
                .set("dtoPackageName", packageBase + ".dto." + className)
                .set("tableName", tableName)
                .set("packageBase", packageBase);

        String serviceTpl = "/service.html";
        render(serviceTpl, set, append);
        return this;
    }

    /**
     * 生成ServiceImpl
     *
     * @param className 类名称
     * @param tableName 表名
     */
    public JFMVCGenerator serviceImpl(String className, String tableName) {
        String packages = toPackages("service.impl");

        String classNameSmall = toClassNameSmall(className);
        String webRootPath = PathKit.getWebRootPath();
        StringBuilder append = new StringBuilder()
                .append(webRootPath)
                .append("/")
                .append(srcFolder)
                .append("/")
                .append(packages.replace(".", "/"))
                .append("/")
                .append(className)
                .append("ServiceImpl.java");
        Kv set = Kv.by("package", packages)
                .set("className", className)
                .set("classNameSmall", classNameSmall)
                .set("modelPackageName", modelPackageName + "." + className)
                .set("servicePackageName", packageBase + ".service." + className)
                .set("dtoPackageName", packageBase + ".dto." + className)
                .set("tableName", tableName)
                .set("packageBase", packageBase);

        String serviceTpl = "/serviceImpl.html";
        render(serviceTpl, set, append);
        return this;
    }

    /**
     * 根据具体魔板生成文件
     *
     * @param templateFileName 模板文件名称
     * @param kv               渲染参数
     * @param filePath         输出目录
     * @return
     */
    public boolean render(String templateFileName, Kv kv, StringBuilder filePath) {
        BufferedWriter output = null;
        try {
            String baseTemplatePath = new StringBuilder(PathKit.getRootClassPath())
                    .append(tpl)
                    .toString();
            File file = new File(filePath.toString());

            File path = new File(file.getParent());
            if (!path.exists()) {
                path.mkdirs();
            }
            output = new BufferedWriter(new FileWriter(file));

            Engine.use()
                    .setBaseTemplatePath(baseTemplatePath)
                    //.setSourceFactory(new ClassPathSourceFactory())
                    .getTemplate(templateFileName)
                    .render(kv, output);

            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (output != null) output.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * 根据自定义内容生成文件
     *
     * @param data     自定义内容
     * @param filePath 输出目录
     * @return
     */
    public boolean render(String data, StringBuilder filePath) {
        BufferedWriter output = null;
        try {
            File file = new File(filePath.toString());
            File path = new File(file.getParent());
            if (!path.exists()) {
                path.mkdirs();
            }
            output = new BufferedWriter(new FileWriter(file));
            output.write(data);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (output != null) output.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * java 代码生成
     */
    public JFMVCGenerator javaRender(String className, String tableName) {
        JFinalModelGenerator.main(null);
        return controller(className).service(className, tableName)
                .serviceImpl(className, tableName);
    }

    /**
     * 生成数据库表
     * TODO tableMeta待完成..
     */
    public JFMVCGenerator tableMeta(List<TableMeta> tableMetas) {
        return this;
    }


    protected class DataGenerator extends DataDictionaryGenerator {
        public DataGenerator(DataSource dataSource, String dataDictionaryOutputDir) {
            super(dataSource, dataDictionaryOutputDir);
        }

        public void rebuildColumnMetas(List<TableMeta> tableMetas) {
            super.rebuildColumnMetas(tableMetas);
        }
    }

    public JFMVCGenerator setPackageBase(String packageBase) {
        this.packageBase = packageBase;
        return this;
    }

    public JFMVCGenerator setBasePath(String basePath) {
        this.basePath = basePath;
        return this;
    }

    public JFMVCGenerator setSrcFolder(String srcFolder) {
        this.srcFolder = srcFolder;
        return this;
    }
}
